package com.minisoft.activity;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.*;

public class LotteryTest {
    @Test
    public void testEmptyList() {
        List<Double> emptyList = Collections.emptyList();
        assertEquals(-1, Lottery.lottery(emptyList));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testInvalidProbability() {
        List<Double> invalidList = Arrays.asList(0.3, -0.2, 0.5);
        Lottery.lottery(invalidList);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testNegativeProbability() {
        List<Double> invalidList = Arrays.asList(0.3, -0.1, 0.5, -0.2);
        assertEquals(2, Lottery.lottery(invalidList));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testZeroProbability() {
        List<Double> zeroList = Arrays.asList(0d, 0d, 0d);
        assertEquals(-1, Lottery.lottery(zeroList));
    }

    @Test
    public void testNormalList() {
        List<Double> normalList = Arrays.asList(0.01,0.3, 0.1, 0.5, 0.1);
        int result = LotteryUtil.lottery(normalList);
        assertTrue(result >= 0 && result < normalList.size());
    }

    @Test
    public void testNormalList2() {
        List<Double> normalList = Arrays.asList(0.01, 0.01, 0.05, 0.05,98.0);
        int result = LotteryUtil.lottery(normalList);
        assertTrue(result >= 0 && result < normalList.size());
    }

    @Test
    public void testMultiThread() throws InterruptedException {
        final List<Double> list = new ArrayList<>(Arrays.asList(0.2, 0.3, 0.5));
        final int[] resultCounts = new int[list.size()];
        final int totalTests = 100000;

        Runnable task = () -> {
            for (int i = 0; i < totalTests; i++) {
                int result = Lottery.draw(list);
                synchronized (resultCounts) {
                    resultCounts[result]++;
                }
            }
        };

        int numThreads = Runtime.getRuntime().availableProcessors();
        ExecutorService executor = Executors.newFixedThreadPool(numThreads);

        for (int i = 0; i < numThreads; i++) {
            executor.execute(task);
        }

        executor.shutdown();
        executor.awaitTermination(10, TimeUnit.MINUTES);

        for (int i = 0; i < list.size(); i++) {
            double actualProbability = list.get(i);
            double expectedProbability = (double) resultCounts[i] / (numThreads * totalTests);
            double error = Math.abs(actualProbability - expectedProbability);
//            assertTrue(error < 0.01);
            System.out.println(error);
        }
    }
}
